﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using UniRlv.COL;
using UniRlv.Utility;
using UniRlv.Utility.Extend;

namespace UniRlv.Utility.Extend
{
    internal class InputDataPrc
    {
        static InputDataPrc _instance = null;

        ConcurrentQueue<List<object>> queDataPrc = null;
        ConcurrentQueue<List<object>> queDataEditPrc = null;

        WorkSpace CurWorkSpace;

        bool bQuit { get; set; }

        Thread td = null;


        public string ErrorString { get; set; }
        public static InputDataPrc GetInstance()
        {
            //return Singleton<WorkSpace>.GetInstance();

            if (_instance == null)
            {
                _instance = new InputDataPrc();
            }

            return _instance;
        }

        public void Init(WorkSpace ws)
        {
            queDataPrc = new ConcurrentQueue<List<object>>();
            queDataEditPrc = new ConcurrentQueue<List<object>>();

            bQuit = false;
            CurWorkSpace = ws;

            td = new Thread(new ThreadStart(DataPrc));
            td.IsBackground = true;//改为后台线程，注意:改变线程从前台到后台不会以任何方式改变它在CPU协调程序中的优先级和状态
            td.Start();
        }

        public bool Quit()
        {
            if (queDataPrc.Count>0)
            {
                ErrorString = "数据未处理完毕，无法退出";
                return false;
            }

            bQuit = true;

            return true;
        }

        public void PutInputData(LineDevice dev, string code)
        {
            List<object> li = new List<object>();

            li.Add(dev);
            li.Add(code);

            queDataPrc.Enqueue(li);
        }

        public void PutEditData(List<string> saCode, exception_proccess act)
        {
            List<object> li = new List<object>();

            li.Add(new List<string>(saCode));
            li.Add(act);

            queDataEditPrc.Enqueue(li);
        }

        void DataPrc()
        {
            Debug.WriteLine("进入数据处理线程");
            while (!bQuit)
            {
                if (queDataPrc.Count > 0)
                {
                    List<object> li = null;
                    bool b = queDataPrc.TryDequeue(out li);

                    if (b && li != null)
                    {
                        LineDevice dev;
                        string code;
                        string msg = string.Empty;
                        int ratio = 1;

                        try
                        {
                            dev = li[0] as LineDevice;
                            code = li[1] as string;
                        }
                        catch (Exception exp)
                        {
                            //Program.AppendExceptionLog("数据处理线程获取队列数据失败：" + exp.Message);
                            Debug.WriteLine("数据处理线程获取队列数据失败：" + exp.Message);
                            ErrorString = exp.Message;
                            Thread.Sleep(50);
                            continue;
                        }

                        en_code_prc prc;

                        if (dev.IO == 1 && dev.deviceType == (int)out_device_type.ODT_PRINTER)
                        {
                            prc = CodePrcUtility.SavePrintCode(code, dev.stationNumber, ref msg);
                        }
                        else
                        {
                            prc = CodePrcUtility.SaveCode(dev, code, ref msg);
                        }

                        if (prc == en_code_prc.CP_NORMAL || prc == en_code_prc.CP_PRC_NORMAL)
                        {
                            if (dev.stationNumber == PublicObject.CurLine.stationQuantity &&
                                (dev.deviceType == (int)in_device_type.IDT_MANUAL_SCANER || dev.deviceType == (int)in_device_type.IDT_UNI_SCANER))
                            {//顶级码并且手工扫描
                                PublicObject.TopMan++;
                            }

                            //2020-12-25 新增
                            if (dev.deviceType == (int)in_device_type.IDT_OCR_CAMERA)
                            {
                                foreach (var item in CurWorkSpace.scanners)
                                {//实现关联码采集器和盒码采集器安装一起，关联码读取成功才触发盒码采集器
                                    if (item.Device.stationNumber == dev.stationNumber+1 && item.Device.twiceScan == 0)
                                    {//父码采集器，非二次扫描
                                        item.Send("T");//触发拍照
                                    }
                                }
                            }
                            if (CurWorkSpace.CodeSaveEvent != null)
                            {
                                if (prc == en_code_prc.CP_NORMAL)
                                {
                                    CurWorkSpace.CodeSaveEvent(this, new CodeSaveEventArg(dev, code, msg, true, prc));

                                    if (dev.IO == 1 && dev.deviceType == (int)out_device_type.ODT_PRINTER)
                                    {//打印设备已打印，只需保存数据即可返回-------
                                        continue;
                                    }

                                    //查询是否需要打印
                                    if (PublicObject.bPrint)
                                    {
                                        foreach (var pi in CurWorkSpace.printerInfos)
                                        {
                                            if (pi.StationNum == dev.stationNumber + 1)
                                            {

                                                int idxPI = CurWorkSpace.printerInfos.IndexOf(pi);
                                                msg = string.Empty;
                                                switch (pi.StationNum)
                                                {
                                                    case 2:
                                                        ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 2];
                                                        //if (PublicObject.arrCode1.Count % ratio == 0 && PublicObject.arrCode1.Count > 0)
                                                        if (PublicObject.arrCode1.Count % ratio == 0 && PublicObject.arrCode1.Count > 0 && PublicObject.arrCode1.Count> PublicObject.arrCode2.Count*ratio)
                                                        {//满整包装
                                                            bool bPrint3 = false;
                                                            //if (CurWorkSpace.PrintOneLabel(2, ref msg))
                                                            //{
                                                                //if (CodePrintEvent!=null)
                                                                //{
                                                                //    CodePrintEvent(this, new CodePrintEventArg(pi, PublicObject.arrCode2[PublicObject.arrCode2.Count-1].code, "打印成功"));
                                                                //}

                                                            //}
                                                            //到这打印数据并未真正保存，只是打印而已

                                                            //判断是否需要打印三级码
                                                            for (int i = 0; i < CurWorkSpace.printerInfos.Count; i++)
                                                            {
                                                                if (CurWorkSpace.printerInfos[i].StationNum == 3)
                                                                {//三级码也需要打印
                                                                    ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 3];
                                                                    
                                                                    //if (PublicObject.arrCode2.Count % ratio == 0 && PublicObject.arrCode2.Count > 0)
                                                                    if ((PublicObject.arrCode2.Count+1) % ratio == 0 && PublicObject.arrCode2.Count > 0 && (PublicObject.arrCode2.Count + 1) > PublicObject.arrCode3.Count * ratio)
                                                                    {//满整包装
                                                                        bPrint3 = true;
                                                                        //if (CurWorkSpace.PrintOneLabel(3, ref msg))
                                                                        //{
                                                                            //if (CodePrintEvent != null)
                                                                            //{
                                                                            //    CodePrintEvent(this, new CodePrintEventArg(CurWorkSpace.printerInfos[i], PublicObject.arrCode3[PublicObject.arrCode3.Count - 1].code, "打印成功"));
                                                                            //}
                                                                            break;
                                                                        //}
                                                                    }
                                                                }
                                                            }

                                                            if (bPrint3)
                                                            {
                                                                CurWorkSpace.PrintTwoLabels(2, 3, true, ref msg);
                                                            }
                                                            else
                                                            {
                                                                CurWorkSpace.PrintOneLabel(2, ref msg);
                                                            }
                                                        }

                                                        break;
                                                    case 3:
                                                        ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 3];

                                                        if (PublicObject.bSecond)
                                                        {//二次扫描
                                                            if (dev.twiceScan == 1)
                                                            {
                                                                if (CodePrcUtility.GetScanTwiceQty() % ratio == 0 && CodePrcUtility.GetScanTwiceQty() > 0 && CodePrcUtility.GetScanTwiceQty() > PublicObject.arrCode3.Count * ratio)
                                                                {//满整包装并且尚未打印，二次采集可能或重复采集
                                                                    bool bPrint4 = false;

                                                                    //if (CurWorkSpace.PrintOneLabel(3, ref msg))
                                                                    //{
                                                                        //if (CodePrintEvent != null)
                                                                        //{
                                                                        //    CodePrintEvent(this, new CodePrintEventArg(pi, PublicObject.arrCode3[PublicObject.arrCode3.Count - 1].code, "打印成功"));
                                                                        //}


                                                                        //判断是否需要打印四级码
                                                                        for (int i = 0; i < CurWorkSpace.printerInfos.Count; i++)
                                                                        {
                                                                            if (CurWorkSpace.printerInfos[i].StationNum == 4)
                                                                            {//四级码也需要打印
                                                                                ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 4];
                                                                                //if (PublicObject.arrCode3.Count % ratio == 0 && PublicObject.arrCode3.Count > 0)
                                                                                if ((PublicObject.arrCode3.Count + 1) % ratio == 0 && PublicObject.arrCode3.Count > 0 && (PublicObject.arrCode3.Count + 1) > PublicObject.arrCode4.Count * ratio)
                                                                                {//满整包装
                                                                                    bPrint4 = true;
                                                                                    //if (CurWorkSpace.PrintOneLabel(4, ref msg))
                                                                                    //{
                                                                                        //if (CodePrintEvent != null)
                                                                                        //{
                                                                                        //    CodePrintEvent(this, new CodePrintEventArg(CurWorkSpace.printerInfos[i], PublicObject.arrCode4[PublicObject.arrCode4.Count - 1].code, "打印成功"));
                                                                                        //}
                                                                                        break;
                                                                                    //}
                                                                                }
                                                                            }
                                                                        }
                                                                    //}
                                                                    if (bPrint4)
                                                                    {
                                                                        CurWorkSpace.PrintTwoLabels(3, 4, true, ref msg);
                                                                    }
                                                                    else
                                                                    {
                                                                        CurWorkSpace.PrintOneLabel(3, ref msg);
                                                                    }

                                                                }
                                                            }
                                                        }
                                                        else
                                                        {

                                                            //if (PublicObject.arrCode2.Count % ratio == 0 && PublicObject.arrCode2.Count > 0)
                                                            if (PublicObject.arrCode2.Count % ratio == 0 && PublicObject.arrCode2.Count > 0 && PublicObject.arrCode2.Count > PublicObject.arrCode3.Count * ratio)
                                                            {//满整包装
                                                                bool bPrint4 = false;

                                                                //if (CurWorkSpace.PrintOneLabel(3, ref msg))
                                                                //{
                                                                    //if (CodePrintEvent != null)
                                                                    //{
                                                                    //    CodePrintEvent(this, new CodePrintEventArg(pi, PublicObject.arrCode3[PublicObject.arrCode3.Count - 1].code, "打印成功"));
                                                                    //}

                                                                    //判断是否需要打印四级码
                                                                    for (int i = 0; i < CurWorkSpace.printerInfos.Count; i++)
                                                                    {
                                                                        if (CurWorkSpace.printerInfos[i].StationNum == 4)
                                                                        {//四级码也需要打印
                                                                            ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 4];
                                                                            //if (PublicObject.arrCode3.Count % ratio == 0 && PublicObject.arrCode3.Count > 0)
                                                                            if ((PublicObject.arrCode3.Count + 1) % ratio == 0 && PublicObject.arrCode3.Count > 0 && (PublicObject.arrCode3.Count + 1) > PublicObject.arrCode4.Count * ratio)
                                                                            {//满整包装
                                                                            bPrint4 = true;
                                                                                //if (CurWorkSpace.PrintOneLabel(4, ref msg))
                                                                                //{
                                                                                    //if (CodePrintEvent != null)
                                                                                    //{
                                                                                    //    CodePrintEvent(this, new CodePrintEventArg(CurWorkSpace.printerInfos[i], PublicObject.arrCode4[PublicObject.arrCode4.Count - 1].code, "打印成功"));
                                                                                    //}
                                                                                    break;
                                                                                //}
                                                                            }
                                                                        }
                                                                    }
                                                                //}
                                                                if (bPrint4)
                                                                {
                                                                    CurWorkSpace.PrintTwoLabels(3, 4, true, ref msg);
                                                                }
                                                                else
                                                                {
                                                                    CurWorkSpace.PrintOneLabel(3, ref msg);
                                                                }
                                                            }

                                                        }
                                                        break;
                                                    case 4:
                                                        ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 4];
                                                        //if (PublicObject.arrCode3.Count % ratio == 0 && PublicObject.arrCode3.Count > 0)
                                                        if (PublicObject.arrCode3.Count % ratio == 0 && PublicObject.arrCode3.Count > 0 && PublicObject.arrCode3.Count > PublicObject.arrCode4.Count * ratio)
                                                        {//满整包装
                                                            if (CurWorkSpace.PrintOneLabel(4, ref msg))
                                                            {
                                                                //if (CodePrintEvent != null)
                                                                //{
                                                                //    CodePrintEvent(this, new CodePrintEventArg(pi, PublicObject.arrCode4[PublicObject.arrCode4.Count - 1].code, "打印成功"));
                                                                //}

                                                            }
                                                        }
                                                        break;
                                                    default:
                                                        break;
                                                }

                                            }
                                        }
                                    }

                                }
                                else
                                {
                                    CurWorkSpace.CodeSaveEvent(this, new CodeSaveEventArg(dev, code, msg, true, prc));
                                    CurWorkSpace.RefreshCodeQty();
                                }

                            }

                            for (int i = 1; i < PublicObject.CurTask.tagLevel; i++)
                            {
                                switch (i)
                                {
                                    case 1:
                                        ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 2];
                                        if (PublicObject.arrCode1.Count % ratio == 0 && PublicObject.arrCode1.Count > 0)
                                        {//满整包装
                                            if (CurWorkSpace.bVoiceTipLevel1)
                                            {
                                                AppHelper.Talk("一级码满包装");
                                            }

                                        }
                                        break;
                                    case 2:
                                        ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 3];
                                        if (PublicObject.arrCode2.Count % ratio == 0 && PublicObject.arrCode2.Count > 0)
                                        {//满整包装
                                            if (CurWorkSpace.bVoiceTip)
                                            {
                                                AppHelper.Talk("二级码满包装");
                                            }

                                        }
                                        break;
                                    case 3:
                                        ratio = CodePrcUtility.GetCurLevelRatios()[PublicObject.CurTask.tagLevel - 4];
                                        if (PublicObject.arrCode3.Count % ratio == 0 && PublicObject.arrCode3.Count > 0)
                                        {//满整包装
                                            if (CurWorkSpace.bVoiceTip)
                                            {
                                                AppHelper.Talk("三级码满包装");
                                            }

                                        }
                                        break;
                                    default:
                                        break;
                                }
                            }

                        }
                        else if (prc == en_code_prc.CP_STEPS)
                        {//手持扫码处理过程
                            if (CurWorkSpace.CodeSaveEvent != null)
                            {
                                //AppHelper.Talk(msg);
                                CurWorkSpace.CodeSaveEvent(this, new CodeSaveEventArg(dev, code, msg, false, prc));
                            }
                        }
                        else//错误处理
                        {

                            if (prc == en_code_prc.CP_PICK && dev.autoPick == 1 && dev.stationNumber == 1)
                            {//一级码自动剔除，无须发命令
                                Console.WriteLine("Pick1\n");
                                PublicObject.Picks1++;
                                CurWorkSpace.CodeSaveEvent(this, new CodeSaveEventArg(dev, code, msg, false, prc));
                                continue;//一级码的解码失败可以直接返回继续处理，采集器自动
                            }

                            if (dev.stationNumber == 1)
                            {
                                if (CurWorkSpace.doDev != null)
                                    CurWorkSpace.doDev.Pick(dev.stationNumber, null);

                                if (dev.deviceType == (int)in_device_type.IDT_OTHERS)
                                {
                                    foreach (var item in CurWorkSpace.scanners)
                                    {
                                        if (item.Device.Equals(dev))
                                        {
                                            item.Send("P");
                                        }
                                    }
                                }

                                if (dev.deviceType == (int)in_device_type.IDT_OCR_CAMERA)
                                {//OCR相机
                                    foreach (var item in CurWorkSpace.scanners)
                                    {
                                        if (item.Device.Equals(dev))
                                        {
                                            item.Send("P");
                                        }
                                    }

                                    //判断是否需要剔除父码
                                    if (WorkSpace.GetInstance().bPickBind && dev.stationNumber == 1)
                                    {
                                        ratio = AppHelper.GetStationRatio(2, PublicObject.CurTask.tagRatio);
                                        if (PublicObject.arrCode2.Count*ratio>PublicObject.arrCode1.Count)
                                        {
                                            PublicObject.arrCode2.RemoveAt(PublicObject.arrCode1.Count/ratio);
                                        }

                                        //2021-01-04添加：海康OCR相机无法实现发命令输出信号，因此通过二级码采集器输出信号
                                        foreach (var item in CurWorkSpace.scanners)
                                        {//实现关联码采集器和盒码采集器安装一起，关联码读取成功才触发盒码采集器
                                            if (item.Device.stationNumber == dev.stationNumber + 1 && item.Device.twiceScan == 0)
                                            {//父码采集器，非二次扫描
                                                item.Send("A");//输出剔除信号
                                            }
                                        }
                                    }
                                }
                            }

                            if (dev.alarm == 1)
                            {
                                if (CurWorkSpace.doDev != null)
                                    CurWorkSpace.doDev.Alarm(dev.stationNumber, null);

                                if (dev.deviceType == (int)in_device_type.IDT_OTHERS)
                                {
                                    foreach (var item in CurWorkSpace.scanners)
                                    {
                                        if (item.Device.Equals(dev))
                                        {
                                            item.Send("A");
                                        }
                                    }
                                }

                            }

                            //判断是否需要剔除子码
                            if (WorkSpace.GetInstance().bPickBind && dev.stationNumber == 2)
                            {
                                ratio = AppHelper.GetStationRatio(2, PublicObject.CurTask.tagRatio);
                                if (PublicObject.arrCode2.Count * ratio < PublicObject.arrCode1.Count)
                                {
                                    string strTmp = "";
                                    if (!CodePrcUtility.DeleteRange1(PublicObject.arrCode2.Count * ratio, (PublicObject.arrCode2.Count + 1) * ratio - 1, ref strTmp))
                                    {
                                        CurWorkSpace.CodeSaveEvent(this, new CodeSaveEventArg(dev, code, strTmp, false, prc));
                                    }
                                }
                            }

                            //if (prc == en_code_prc.CP_PICK)
                            //{//所有剔除都计数
                            switch (dev.stationNumber)
                                {
                                    case 1:
                                        PublicObject.Picks1++;
                                        break;
                                    case 2:
                                        PublicObject.Picks2++;

                                        if (CurWorkSpace.bVoiceTip)
                                        {
                                            AppHelper.Talk("二级码剔除");
                                        }

                                        break;
                                    case 3:
                                        PublicObject.Picks3++;
                                        if (CurWorkSpace.bVoiceTip)
                                        {
                                            AppHelper.Talk("三级码剔除");
                                        }

                                        break;
                                    default:
                                        break;
                                }

                                if (dev.stationNumber == PublicObject.CurLine.stationQuantity)
                                {//顶级码
                                    PublicObject.TopLoss++;
                                }
                            //}

                            if (CurWorkSpace.CodeSaveEvent != null)
                            {
                                CurWorkSpace.CodeSaveEvent(this, new CodeSaveEventArg(dev, code, msg, false, prc));
                            }

                        }

                    }
                    else
                    {

                    }
                }
                else if (queDataEditPrc.Count > 0)
                {
                    List<object> li = null;
                    bool b = queDataEditPrc.TryDequeue(out li);

                    if (b && li != null)
                    {
                        List<string> codes;
                        exception_proccess act;

                        try
                        {
                            codes = li[0] as List<string>;
                            act = (exception_proccess)li[1];
                        }
                        catch (Exception exp)
                        {
                            //Program.AppendExceptionLog("数据处理线程获取队列数据失败：" + exp.Message);
                            Debug.WriteLine("数据处理线程获取队列数据失败：" + exp.Message);
                            ErrorString = exp.Message;
                            Thread.Sleep(50);
                            continue;
                        }

                        bool iRes = false;
                        string strMsg = string.Empty;

                        try
                        {
                            switch (act)
                            {
                                case exception_proccess.EP_APPEND:
                                    iRes = CodePrcUtility.AppendCode(codes, 1, ref strMsg);
                                    break;
                                case exception_proccess.EP_DELETE_RANGE:
                                    iRes = CodePrcUtility.DeleteRange(Convert.ToInt32(codes[0]), Convert.ToInt32(codes[1]), Convert.ToInt32(codes[2]), ref strMsg);
                                    break;
                                case exception_proccess.EP_INSERT:
                                    iRes = CodePrcUtility.InsertCode(codes, ref strMsg);
                                    break;
                                case exception_proccess.EP_LABEL_BATCH_DELETE:
                                    iRes = CodePrcUtility.DeleteInBatch(codes, ref strMsg);
                                    break;
                                case exception_proccess.EP_LABEL_PACKAGE_DELETE:
                                    iRes = CodePrcUtility.DeletePackage(codes[0], ref strMsg);
                                    break;
                                case exception_proccess.EP_LABEL_SWITCH:
                                    iRes = CodePrcUtility.ReplaceCode(codes, ref strMsg);
                                    break;
                                case exception_proccess.EP_QUERY_RLT:
                                    CodePrcUtility.CheckRlt(codes, ref strMsg);
                                    iRes = false;
                                    break;
                                case exception_proccess.EP_SCAN_AUTO:
                                    iRes = CodePrcUtility.InsertCode21(codes, ref strMsg);
                                    break;
                                default:
                                    strMsg = "操作不支持";
                                    break;
                            }
                        }
                        catch (Exception exp)
                        {
                            iRes = false;
                            strMsg = exp.Message;
                        }

                        if (iRes)
                        {
                            
                            if (CurWorkSpace.CodeEditEvent != null)
                            {
                                CurWorkSpace.CodeEditEvent(this, new CodeEditEventArg(codes, act, "操作成功！"));
                            }
                        }
                        else
                        {
                            if (CurWorkSpace.CodeEditEvent != null)
                            {
                                CurWorkSpace.CodeEditEvent(this, new CodeEditEventArg(codes, act, strMsg));
                            }
                        }
                    }
                    else
                    {
                        
                    }
                }
                else
                {
                    Thread.Sleep(50);
                }
            }

            Debug.WriteLine("退出数据处理线程");
        }
    }
}
